/*
        AVGA 0.22 test application
        
        This time the driver comes preconfigured to VGA 640x480@60Hz.
        Final resolution: 112x112x4bpp.
        Target MCU: ATMega168 @ 25.00000 MHz.

        Pinout:  VSYNC @ PIN15 (PB1)
                 HSYNC @ PIN16 (PB2)
                 pixelstream @ upper nibble of PORTD
*/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "AVGA/avga.h"
#include "tileset.h" 

//memory for the driver.
unsigned char screen[DRIVER_SCREEN_SIZE];
const unsigned char pgmmap[] PROGMEM = TILESET;
unsigned char rammap[DRIVER_RAMMAP_SIZE];


//user graphical objects
const unsigned char avrlogo[] PROGMEM = {13,14,15,16,17,18,19,20};
const unsigned char avgalogo[] PROGMEM = {129,130,131,132,133,134,135,136,137,138,139,
										 140,141,142,143,144,145,146,147,148,149,150,
										 151,152,153,154,155,156,157,158,159,160,161};


//Some high-level helpful functions.
static unsigned int DrawCenteredText(int y, PGM_P txt);
static void DrawInt16( int x, int y, unsigned int i );
static void DrawPalette( unsigned char x, unsigned char y );


//demonstration
static inline void intro();
static inline void demo1();
static inline void demo2();

int main( void )
{
	driver_mmap(screen, pgmmap, rammap);

	//
	// NOTE: When changing the video standard (or resolution), one should
	//		 always check the following:
	//
	//		 1. VIDEO_YPOS (config_screen.h) - this value must
	//		 be lower or equal than active line count in the 
	//		 video standard.
	//
	//		 2. The nominal line period must be greater than
	//		 DRIVER_RESX*5 + overhead (in clocks). If this
	//		 condition is not met, the scan line interrupt
	//		 can overflow. Then DRIVER_WIDTH (config_screen.h)
	//		 should be decreased.
	//

	video_init(VGA2);

	video_enable(); 	//start driver.
	wait_seconds(1); 	//wait for display to sync

	intro();
	demo1();
	demo2();
}


static inline void intro()
{
	driver_fill(128);  //clear screen
	wait_seconds(1);

	driver_set_block(0, 0, 4);
	driver_set_block(DRIVER_LAST_COLUMN, 0, 4);
	driver_set_block(0, DRIVER_LAST_ROW, 4);
	driver_set_block(DRIVER_LAST_COLUMN, DRIVER_LAST_ROW, 4);
	DrawCenteredText(5, PSTR("Please,adjust\nXPOS, YPOS\nto fit!"));
	wait_seconds(4);

	driver_fill(128);
	wait_seconds(1);
	DrawCenteredText(1, PSTR("Hello, world!\n\n      based\nCOLOR game\nplatform\n" __DATE__));
	background_draw(3, 4, avrlogo, 4, 2);
	wait_seconds(5);

	driver_fill(128);
	DrawCenteredText(2, PSTR("5 ticks/pixel\n\navga.\nprometheus4.\ncom"));
	DrawPalette(DRIVER_RESX/2-48,DRIVER_RESY-16); 
	wait_seconds(5);
	overlay_release();   //palette...
}

static inline void demo1()
{
	int x, y;
	driver_fill(128);
	wait_seconds(1);
	driver_fill(21);
	for(y=DRIVER_LAST_ROW;y>=0;y--)
	{
		for(x=0;x<DRIVER_LAST_COLUMN;x++)
		{
			driver_set_block(x,y,23);
			sync();
		}
		for(x=DRIVER_LAST_COLUMN;x>=0;x--)
		{
			driver_set_block(x,y,22);
			sync();
		}
	}
	wait_seconds(3);
}


static inline void demo2()
{
	unsigned int i;

	driver_fill(128);
	wait_seconds(1);

	unsigned char x1=50, x2=60, x3=70, x4=80, x5=40, y1=20, y2=80, y3=78,y4=65,y5=45;
	signed char dx1=1, dx2=-1, dx3=1, dx4=-1, dx5=1, dy1=-1, dy2=1, dy3=1, dy4=-1, dy5=1;

	driver_fill(128);
	background_draw(1,5,avgalogo,11,3);
	wait_seconds(1);

	unsigned long l=0;

	while(1)
	{
		if(i >= 60) 
		{
				int tmp = (l*7) / 1000;

				DrawInt16(4, 10, tmp / 1000); //show remaining time
				driver_print_C(5,10,".");
				DrawInt16(6, 10, tmp % 1000);
				driver_print_C(2,12,"MIPS left");

				l=0;
				i=0;
		}

		overlay_clear();
		overlay_draw_sprite(x1, y1, 1);
		overlay_draw_sprite(x2, y2, 2);
		overlay_draw_sprite(x3, y3, 3);
		overlay_draw_sprite(x4, y4, 5);
		overlay_draw_sprite(x5, y5, 6);


		x1+=dx1; if(x1 >= DRIVER_RESX-8 || x1 <= 0) dx1=-dx1;
		y1+=dy1; if(y1 >= DRIVER_RESY-8 || y1 <= 0) dy1=-dy1;

		x2+=dx2; if(x2 >= DRIVER_RESX-8 || x2 <= 0) dx2=-dx2;
		y2+=dy2; if(y2 >= DRIVER_RESY-8 || y2 <= 0) dy2=-dy2;

		x3+=dx3; if(x3 >= DRIVER_RESX-8 || x3 <= 0) dx3=-dx3;
		y3+=dy3; if(y3 >= DRIVER_RESY-8 || y3 <= 0) dy3=-dy3;

		x4+=dx4; if(x4 >= DRIVER_RESX-8 || x4 <= 0) dx4=-dx4;
		y4+=dy4; if(y4 >= DRIVER_RESY-8 || y4 <= 0) dy4=-dy4;

		x5+=dx5; if(x5 >= DRIVER_RESX-8 || x5 <= 0) dx5=-dx5;
		y5+=dy5; if(y5 >= DRIVER_RESY-8 || y5 <= 0) dy5=-dy5;

			
		l += sync();

		i++;
		
	}
}




//
// High-level drawing functions.
//

static void DrawInt16(int x, int y, unsigned int i)
{
	unsigned char str[6];
	itoa(i,str,10);
	driver_print(x, y, str);
}

static unsigned int DrawCenteredText(int y, PGM_P  txt)
{
	unsigned char c, width=0, height=0;	   

	do
	{
		PGM_P txt2 = txt;
		unsigned char i=0;

		while(1)
		{
			c = pgm_read_byte(txt++);
			if(!c || c == '\n') break;
			i++;
		}

		unsigned char* ptr = &driver_get_block((DRIVER_COLUMNS/2) - i/2, y);
		memcpy_P(ptr, txt2, i);
		y+=2;

		if(i>width) width=i;
		height+=2;
	}
	while(c);

	return (width) | ((height-1)<<8);
}

static void DrawPalette( unsigned char x, unsigned char y)
{
	unsigned char xp, yp;

	for(yp=0;yp<8;yp++)
	for(xp=0;xp<96;xp++) 
	overlay_putpixel(x+xp, y+yp, xp/6);
}








